<?php
declare (strict_types=1);

namespace app\common\service;

use app\common\model\AdminLoginLogModel;
use app\common\model\AdminRoleModel;
use app\common\model\AdminUserModel;
use app\common\model\DataSummaryAdminModel;
use think\facade\Cache;

class AdminUserService
{

    public static $ins = false;
    public $cookie_name = 'auth'; //后台登录的cookie名称
    public $error_num = 5;//允许错误的次数
    public $error_time = 300;//操作超过错误次数，等待时间：秒
    public $login_expire = 30; //登录有效期:天
    public $error = ''; //错误信息

    private function __construct()
    {
    }

    /*
     * 单例模式
    */
    public static function ins(): self
    {
        if (self::$ins === false) {
            self::$ins = new self();
        }
        return self::$ins;
    }

    /*
     * @title 获取当前登录的用户信息
     * */
    public function getUserInfo()
    {
        $cooke_val = cookie($this->cookie_name);
        if (!is_string($cooke_val) || empty($cooke_val)) {
            return false;
        }
        return Cache::store('redis')->get((string)$cooke_val);
    }

    /*
     * @title 检查登录状态
     * */
    public function checkLogin()
    {
        $userInfo = $this->getUserInfo();
        if (!$userInfo) {
            return false;
        }
        $data = AdminUserModel::where('uid', $userInfo['uid'])->find();
        if (!$data) {
            return false;
        }
        if (!isset($userInfo['password']) || $userInfo['password'] != $data->getAttr('password')) {
            return false;
        }
        if ($data->getAttr('status') != 1) {
            return false;
        }
        //检查单点登录
        if ($data->getAttr('sso_status') == 1) {
            $string = cookie($this->cookie_name);
            $check_str = Cache::store('redis')->get((string)$userInfo['uid']);
            if ($check_str != $string) {
                return false;
            }
        }
        return $userInfo;
    }

    /*
     * @title 账号密码登录
     * @param string $username 唯一用户名或者手机号
     * @param string $password 密码
     * @return bool|array
     * */
    public function login(string $username, string $password)
    {
        if (preg_match("/^1[3456789]\d{9}$/", $username)) {
            $field = 'phone';
        } else {
            $field = 'username';
        }
        $data = AdminUserModel::where($field, $username)->find();
        if (!$data) {
            $this->error = '用户没有找到';
            return false;
        }
        if ($data->getAttr('status') != 1) {
            $this->error = '该用户已经被禁用,请联系管理员';
            return false;
        }
        $role_data = AdminRoleModel::where('role_id', $data->getAttr('role_id'))->find();
        if (!$role_data) {
            $this->error = '没有找到对应的角色,请联系管理员';
            return false;
        }
        if ($role_data->getAttr('status') != 1) {
            $this->error = '角色已经被禁用,请联系管理员';
            return false;
        }

        $last_login_time = AdminLoginLogModel::where('uid', $data->getAttr('uid'))->order('id desc')->value('login_time');

        $reset = 0;
        if (is_null($last_login_time) || ((time() - strtotime($last_login_time)) > $this->error_time)) { //已经超过限制时间 允许从新尝试登录
            $reset = 1;
        } else {
            if ($data->getAttr('error_num') >= $this->error_num) {
                $this->error = "错误次数输入过多,请稍等再试";
                return false;
            }
        }
        $sysPassword = $this->createPassword($password, $data->getAttr('salt'));
        if ($sysPassword != $data->getAttr('password')) {
            if ($reset) {
                $num = 1;
            } else {
                $num = $data->getAttr('error_num') + 1;
            }

            (new AdminLoginLogModel())->addLog($data->getAttr('uid'), $username, request()->ip(), 0, $password);

            AdminUserModel::update(['error_num' => $num], ['uid' => $data->getAttr('uid')]);
            $this->error = "密码不正确";
            return false;
        }
        //密码验证通过,更新用户的信息,设置登录状态
        AdminUserModel::update(['error_num' => 0], ['uid' => $data->getAttr('uid')]);
        $return_info = $data->toArray();
        $return_info['role_name'] = $role_data->getAttr('name');
        (new AdminLoginLogModel())->addLog($data->getAttr('uid'), $username, request()->ip(), 1);
        return $return_info;
    }

    /*
     * @title 设置登录状态
     * @param array $userInfo 用户的信息
     * @param int $remember 是否记录登录状态
     * @return bool
     * */
    public function setLogin(array $userInfo, int $remember = 0): bool
    {
        $code = md5($userInfo['uid'] . uniqid() . microtime());
        $expire = 86400;
        if ($remember != 0) {
            $expire = $this->login_expire * $expire;
        }
        //设置单点登录信息
        Cache::store('redis')->set((string)$userInfo['uid'], $code, $expire);
        //设置登录信息
        cookie($this->cookie_name, $code, $expire);
        Cache::store('redis')->set((string)$code, $userInfo, $expire);
        return true;
    }

    /*
     * @title 清除登录状态
     * @return bool
     * */
    public function clearLogin(): bool
    {
        $cooke_val = cookie($this->cookie_name);
        Cache::store('redis')->delete($cooke_val);
        cookie($this->cookie_name, null);
        return true;
    }

    /*
     * @title 创建密码的加密方式
     * @param string $password 密码
     * @param string $salt随机字符串
     * @return string
     * */
    public function createPassword(string $password, string $salt): string
    {
        return md5($password . $salt);
    }


    /*
     * @title 获取日期范围的登录统计信息
     * @param string $date 日期
     * @return array
     * */
    public function loginInfo(string $date): array
    {
        $map = [
            ['login_time', '>=', $date . ' 00:00:00'],
            ['login_time', '<=', $date . ' 23:59:59']
        ];

        $info = AdminLoginLogModel::where($map)
            ->field(
                'count(distinct(uid)) as login_user,
            count(uid) as login_num,
            sum(if(status=1,1,0)) as login_success_num,
            sum(if(status=0,1,0)) as login_fail_num'
            )
            ->find();

        $login_success_user = AdminLoginLogModel::where($map)
                ->where('status', 1)
                ->group('uid')
                ->count('id') ?? 0;

        $login_fail_user = AdminLoginLogModel::where($map)
                ->where('status', 0)
                ->group('uid')
                ->count('id') ?? 0;

        if (empty($info) || is_null($info->getAttr('login_success_num'))) {
            return [
                'login_user' => 0, //登录用户数
                'login_num' => 0, //登录次数
                'login_success_user' => 0,//登录成功用户数
                'login_fail_user' => 0,//登录失败用户数
                'login_success_num' => 0,//登录成功次数
                'login_fail_num' => 0,//登录失败次数
            ];
        }
        return array_merge($info->toArray(), ['login_success_user' => $login_success_user, 'login_fail_user' => $login_fail_user]);
    }

    /*
     * @title 获取指定日期的折线统计数据信息
     * @param string $s 起始日期
     * @param string $e 结束日期
     * @param array
     * */
    public function lineChartData(string $s, string $e): array
    {
        $legend_list = [
            'login_user' => '登录人数',
            'login_num' => '登录次数',
            'login_success_num' => '登录成功次数',
            'login_fail_num' => '登录失败次数',
            'login_success_user' => '登录成功人数',
            'login_fail_user' => '登录失败人数',
            'visit_user' => '访问人数'
        ];

        $list = DataSummaryAdminModel::where('date', '>=', $s)
            ->where('date', '<=', $e)
            ->order('date asc')
            ->select()
            ->toArray();

        if (empty($list)) return [];

        $legend = array_values($legend_list);
        $date = array_column($list, 'date');
        $series = [];
        foreach ($legend_list as $k => $v) {
            $series[] = [
                'name' => $v,
                'type' => 'line',
                //'stack' => '总量',
                'smooth' => true,
                'data' => array_column($list, $k)
            ];
        }

        return [
            'legend' => $legend,
            'date' => $date,
            'series' => $series
        ];
    }


}